package com.zidongxiangxi.sharding.job.core.listener;

import com.zidongxiangxi.sharding.job.core.ShardingJob;
import com.zidongxiangxi.sharding.job.core.node.ShardingNode;
import org.apache.curator.framework.recipes.cache.TreeCacheEvent.Type;

/**
 * 分片变更监听
 *
 * @author chenxudong
 * @date 2021/02/19
 */
public class ShardingNodeChangeListener extends AbstractNodeChangeListener {
    private final ShardingJob job;
    private final ShardingNode shardingNode;

    public ShardingNodeChangeListener(ShardingJob job) {
        this.job = job;
        this.shardingNode = job.getShardingNode();
    }

    @Override
    public boolean canHandleChange(String path, Type eventType) {
        return !job.isShutdown();
    }

    @Override
    void dealDataChange(String path, Type eventType, String data) {
        if (isReShardingFinish(path, eventType)) {
            job.resume();
        } else if (isReShardingStart(path, eventType)) {
            job.pause();
        } else if (isShardingItemInstanceCreate(path, eventType) || isShardingItemInstanceUpdate(path, eventType)) {
            job.addShardingItem(getShardingItemFromPath(path), data);
        } else if (isShardingItemInstanceDelete(path, eventType)) {
            job.removeShardingItem(getShardingItemFromPath(path), data);
        }
    }

    private boolean isReShardingFinish(final String path, final Type eventType) {
        return shardingNode.isProcessingPath(path) && Type.NODE_REMOVED == eventType;
    }

    private boolean isReShardingStart(final String path, final Type eventType) {
        return shardingNode.isProcessingPath(path) && Type.NODE_ADDED == eventType;
    }

    private boolean isShardingItemInstanceCreate(final String path, final Type eventType) {
        return shardingNode.isShardingItemInstancePath(path) && Type.NODE_ADDED == eventType;
    }

    private boolean isShardingItemInstanceUpdate(final String path, final Type eventType) {
        return shardingNode.isShardingItemInstancePath(path) && Type.NODE_UPDATED == eventType;
    }

    private boolean isShardingItemInstanceDelete(final String path, final Type eventType) {
        return shardingNode.isShardingItemInstancePath(path) && Type.NODE_REMOVED == eventType;
    }

    private String getShardingItemFromPath(String path) {
        String shardingItem = path.substring(0, path.lastIndexOf("/"));
        shardingItem = shardingItem.substring(shardingItem.lastIndexOf("/") + 1);
        return shardingItem;
    }
}
